// Compiler for PHP (aka KPHP)
// Copyright (c) 2020 LLC «V Kontakte»
// Distributed under the GPL v3 License, see LICENSE.notice.txt

#pragma once

#include <signal.h>
#include <stddef.h>
#include <sys/types.h>

#include "common/cycleclock.h"
#include "common/wrappers/likely.h"

enum class ExtraSignalAction { GENERATE_COREDUMP = 1 };

double dl_time();

sigset_t dl_get_empty_sigset();
void dl_sigaction(int sig, void (*handler)(int), sigset_t mask, int flags, void (*action)(int, siginfo_t*, void*));
void dl_signal(int sig, void (*handler)(int));
void dl_restore_signal_mask();
void dl_block_all_signals();
void dl_allow_all_signals();
void dl_unblock_signal(int sig);

void dl_print_backtrace(void** trace, int trace_size);
void dl_print_backtrace();
void dl_print_backtrace_gdb();

void dl_set_default_handlers();

char* dl_pstr(char const* message, ...) __attribute__((format(printf, 1, 2)));

const char* dl_get_assert_message() noexcept;

void dl_assert__(const char* expr, const char* file_name, const char* func_name, int line, const char* desc, int use_perror, int generate_coredump);

#define dl_assert_impl(f, str, use_perror, generate_coredump)                                                                                                  \
  if (unlikely(!(f))) {                                                                                                                                        \
    dl_assert__(#f, __FILE__, __FUNCTION__, __LINE__, str, use_perror, generate_coredump);                                                                     \
  }

#define dl_assert(f, str) dl_assert_impl(f, str, 0, 0)
#define dl_passert(f, str) dl_assert_impl(f, str, 1, 0)
#define dl_assert_with_coredump(f, str) dl_assert_impl(f, str, 0, 1)
#define dl_unreachable(str) dl_assert(0, str)

struct pid_info_t {
  unsigned long long utime;
  unsigned long long stime;
  unsigned long long cutime;
  unsigned long long cstime;
  unsigned long long starttime;
};

struct mem_info_t {
  uint32_t vm_peak;
  uint32_t vm;
  uint32_t rss_peak;
  uint32_t rss;
  uint32_t rss_file;
  uint32_t rss_shmem;
};

struct process_rusage_t {
  double user_time;
  double system_time;
  long voluntary_context_switches;
  long involuntary_context_switches;
};

mem_info_t get_self_mem_stats();
int get_pid_info(pid_t pid, pid_info_t* info);
unsigned long long get_pid_start_time(pid_t pid);
int get_cpu_total(unsigned long long* cpu_total);
process_rusage_t get_rusage_info();
